/**
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

package com.waln.notifying.unread;

import java.beans.PropertyVetoException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.UUID;

import com.waln.notifying.unread.args.List;
import com.waln.notifying.unread.args.Count;
import com.waln.notifying.unread.args.Read;

import pittypat.FunctionModel;
import pittypat.IAsyncProgress;
import pittypat.INotificationService;
import pittypat.NotificationList;
import pittypat.configuration.ConfigException;

/**
 * 向客户端提供通知中心相关的功能。
 */
public final class NotificationService implements INotificationService {
	private Api api;

	/**
	 * 初始化 NotificationService 类的新实例。
	 */
	public NotificationService() {
		this.api = new Api();
	}

	/**
	 * 加载指定用户的新通知的数目。
	 * 
	 * @param userId
	 *            用户的 Id。
	 * @param progress
	 *            跟踪和汇报异步操作的进度。
	 * @return 目标用户新通知的数目。
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws PropertyVetoException
	 * @throws SQLException
	 * @throws ConfigException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws UnsupportedEncodingException
	 * @throws ClassNotFoundException
	 * @throws IllegalArgumentException
	 */
	@Override
	public long count(UUID userId, IAsyncProgress progress) throws InstantiationException, IllegalAccessException,
			IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException, InvocationTargetException,
			NoSuchMethodException, SecurityException, ConfigException, SQLException, PropertyVetoException {
		FunctionModel<Count> model = new FunctionModel<>(Count.class);
		model.getArgs().receiverId = userId;

		this.api.count(model, progress);

		return model.getArgs().total;
	}

	/**
	 * 加载指定用户的新通知的列表。
	 * 
	 * @param userId
	 *            用户的 Id。
	 * @param progress
	 *            跟踪和汇报异步操作的进度。
	 * @return 目标用户新通知的列表。
	 * @throws PropertyVetoException
	 * @throws SQLException
	 * @throws ConfigException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws UnsupportedEncodingException
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	@Override
	public NotificationList list(UUID userId, IAsyncProgress progress)
			throws IllegalArgumentException, IllegalAccessException, InstantiationException, ClassNotFoundException,
			UnsupportedEncodingException, InvocationTargetException, NoSuchMethodException, SecurityException,
			ConfigException, SQLException, PropertyVetoException {
		FunctionModel<List> model = new FunctionModel<List>(List.class);
		model.getArgs().userId = userId;

		this.api.list(model, progress);

		return new NotificationList(model.getArgs().total, Notification.From(model.getArgs().notifications));
	}

	/**
	 * 将指定的通知记录标记为已读。
	 * 
	 * @param userId
	 *            用户的 Id。
	 * @param notificationId
	 *            要标记为已读的通知记录的 Id。
	 * @param progress
	 *            跟踪和汇报异步操作的进度。
	 * @return 通知被标记的时间。
	 * @throws PropertyVetoException
	 * @throws SQLException
	 * @throws ConfigException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws UnsupportedEncodingException
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	@Override
	public LocalDateTime read(UUID userId, UUID notificationId, IAsyncProgress progress)
			throws IllegalArgumentException, IllegalAccessException, InstantiationException, ClassNotFoundException,
			UnsupportedEncodingException, InvocationTargetException, NoSuchMethodException, SecurityException,
			ConfigException, SQLException, PropertyVetoException {
		FunctionModel<Read> model = new FunctionModel<>(Read.class);
		model.getArgs().userId = userId;
		model.getArgs().id = notificationId;

		this.api.read(model, progress);

		return model.getArgs().readTime;
	}
}
